local httparg    = require("shared.api.httparg")
local response   = require("shared.api.response")
local def        = require("shared.api.def")
local config     = require("config")
local tag        = httparg.tag()
local assertion  = httparg.assertion
local util                  = require "proxy.game.common.util"
local fill_response_header  = util.fill_response_header
local is_match_content_type = util.is_match_content_type
local get_content_decoder   = util.get_content_decoder
local ERROR_CODE = def.ERROR_CODE

local cjson = require "cjson.safe"
      cjson.encode_max_depth(32)
      cjson.decode_max_depth(32)


local ARGS = {
    -- exist body?
    tag.body('json', 'required'),

    username   = tag.json.username   ('string', 'required', assertion.non_empty_string()),
    account    = tag.json.account    ('string', 'required', assertion.non_empty_string()),
    coin_token = tag.json.coin_token ('string', 'required', assertion.non_empty_string()),
    currency   = nil,
    alliance   = nil,
}

-- use coin_toke to get currency
do
    ARGS.coin_token = string.upper(ARGS.coin_token)

    local currency = config.VAR.COIN_TOKEN_MAP[ARGS.coin_token]
    if not currency then
        response.error(ERROR_CODE.UNKNOWN_COIN_TOKEN)
    end
    ARGS.currency = currency
end
-- set alliance
do
    ARGS.alliance = "muse"
end


local RESULT = {}
local dataapi                = require("shared.api.dataapi")
local payment_api            = require("shared.api.paymentgatewayapi")
local payment_channel_helper = require("shared.api.payment-channel-helper")


local headers = ngx.req.get_headers()
do
  headers['X-Forwarded-For'] = ngx.var.proxy_add_x_forwarded_for
  for k,v in pairs(headers) do
    local low_header = string.lower(k)
    if low_header == "x-http-method-override" or
       low_header == "accept-encoding" then
      headers[k] = nil
    end
  end
end

-- get player market and address record
local MARKET
local ADDRESSES
do
  local reply, err = dataapi.account.view_wallet_address(
    {
      username   = ARGS.username,
      alliance   = ARGS.alliance,
      coin_token = ARGS.coin_token,
      currency   = ARGS.currency,
    })

  if err then
    if err.message ~= def.ERROR_CODE.NO_CONTENT then
      response.error(err)
    end
  else
    -- export
    MARKET    = reply.assigned_market
    ADDRESSES = reply.addresses
  end
end


-- have addresses then verify addresses
if ADDRESSES and #ADDRESSES > 0 and #ADDRESSES[1].addresses > 0 and ADDRESSES[1].addresses[1] ~= '*' then
  do
    -- get market and address
    local _market    = MARKET
    local _addresses = ADDRESSES[1].addresses

    -- verify address
    do
      local reply, err = payment_api.verify_wallet_address(
        headers,
        _market,
        {
          coin_token = ARGS.coin_token,
          addresses  = _addresses,
        })

      if err then
        response.error(err)
      end

      -- if address is valid then return address
      if #reply.managed_addresses > 0 then
        RESULT.address = reply.managed_addresses[1]
        response.success(RESULT)
      end
    end
  end
end


-- if not get valid address, need to take now address and update address record
do
  -- get wallet address policy
  local PAYMENT_CHANNEL_POLICY
  do
    local reply, err = dataapi.account.view_wallet_address_policy(
      {
        policy     = "deposit",
        username   = ARGS.username,
        alliance   = ARGS.alliance,
        currency   = ARGS.currency,
        coin_token = ARGS.coin_token,
      })

    if err then
      response.error(err)
    end

    if (not reply) or #reply.content == 0 then
      response.error({
          message     = def.ERROR_CODE.UNKNOWN_FAILTURE,
          description = "missing payment channel policy",
      })
    end

    -- export
    PAYMENT_CHANNEL_POLICY = reply.content
  end

  -- get payment_channel
  local ADDRESS = ""
  local PAYMENT_CHANNEL = ""
  local INVALID_PAYMENT_CHANNEL = {}
  repeat
    PAYMENT_CHANNEL = payment_channel_helper.get_payment_channel(PAYMENT_CHANNEL_POLICY, INVALID_PAYMENT_CHANNEL, MARKET)

    -- when no have valid payment channel return error
    if PAYMENT_CHANNEL == "" then
      response.error(def.ERROR_CODE.MISSING_PAYMENT_CHANNEL)
    end

    -- take address
    do
      local reply, err = payment_api.take_wallet_address(
        headers,
        PAYMENT_CHANNEL,
        {
          coin_token = ARGS.coin_token,
          username   = ARGS.username,
          account    = ARGS.account,
          alliance   = ARGS.alliance,
        })

      if err or (not reply) or (not reply.addresses) or #reply.addresses[1] == 0 then
        -- add invalid payment_channel
        table.insert(INVALID_PAYMENT_CHANNEL, PAYMENT_CHANNEL)
      else
        -- export
        ADDRESS = reply.addresses[1]
      end
    end
  until(ADDRESS ~= "")


  -- update player market and address
  do
    local reply, err = dataapi.account.put_wallet_address(
      {
        username   = ARGS.username,
        alliance   = ARGS.alliance,
        address    = ADDRESS,
        market     = PAYMENT_CHANNEL,
        currency   = ARGS.currency,
        coin_token = ARGS.coin_token,
      })

    if err then
      response.error(err)
    end
  end

  -- export
  do
    RESULT.address = ADDRESS
  end
end

-- response
response.success(RESULT)
